"use client"

import type React from "react"

import { useState, useEffect, useRef, useCallback } from "react"
import { Button } from "@/components/ui/button"
import { Progress } from "@/components/ui/progress"
import { Input } from "@/components/ui/input"
import {
  BookOpen,
  Heart,
  User,
  CheckCircle,
  HelpCircle,
  SkipForward,
  PlusCircle,
  BookText,
  LayoutGrid,
  Undo2,
  Clock,
  X,
  FileText,
  Eye,
  ChevronLeft,
  ChevronRight,
  ArrowLeft,
  Trash2,
  Search,
  Lock,
  AlertCircle,
} from "lucide-react"
import { useRouter } from "next/navigation"
import { BASE_URL } from "@/lib/config"
import axios from "axios"
import {UserInfo} from "@/components/userinfo";
import useAppStore from "@/store/app.store";
import VisibleControl from "@/components/visibleControl";
import CharDetailModal from "@/app/proofread/components/charDetailModal";
import { toast } from '@/hooks/use-toast'
import {Toaster} from "@/components/ui/toaster";

// 类型定义扩展
interface Char {
  id: string
  content: string
  position: number
  ziUrl?: string
  skipped?: boolean
  inserted?: boolean
  insertedAfter?: number
  empty?: boolean
}

// 新增：获取原文字符的API（假设接口为/jiaodui/task-chars/yuanwen）
async function getOriginalChars(yeId: string) {
  try {
    const response = await axios.get(`${BASE_URL}/jiaodui/task-chars/yuanwen`, {
      params: { taskNum: Number(yeId) },
      timeout: 30000,
    });
    if (response.data && response.data.code === 200) {
      return Array.isArray(response.data.data) ? response.data.data : [];
    }
    return [];
  } catch (error: any) {
    return Array.from({ length: 100 }, (_, i) => ({
      id: `mock-${i}`,
      content: `字${i + 1}`,
      position: i,
      ziUrl: "/images/origin01.png"
    }));
  }
}
async function getCharDetail(id: string) {
  const response = await axios.get(`${BASE_URL}/jiaodui/char-detail`, {
    params: { ziId: id },
    timeout: 30000,
  });
  if (response.data && response.data.code === 200) {
    return response.data.data
  }
  return [];
}

// 验证任务代码
async function validateTaskCode(taskCode: string) {
  try {
    // 调用后端接口校验，使用正确的参数名taskNum
    const res = await axios.get(`${BASE_URL}/jiaodui/task-exist`, {
      params: { taskNum: Number(taskCode) },
      timeout: 30000,
    });
    if (res.data && res.data.code === 200 && res.data.data === true) {
      // 任务存在，返回任务编号(确保是字符串类型)
      return { success: true, yeId: String(taskCode), message: "验证成功" };
    } else {
      return { success: false, yeId: "", message: "任务代码无效" };
    }
  } catch (error) {
    return { success: false, yeId: "", message: "验证失败，请稍后重试" };
  }
}

// 固定每页100个图片框，列数根据屏幕宽度自适应
let PAGE_SIZE = 100
// 各屏幕尺寸下的列数配置
const DESKTOP_COLUMNS = 10
const TABLET_COLUMNS = 8
const MOBILE_COLUMNS = 5

// 获取当前页字符并补空（为了古文模式布局特殊处理）
function getCurrentPageCharsWithPadding(chars: any[], currentPage: number) {
  const startIndex = (currentPage - 1) * PAGE_SIZE
  const endIndex = Math.min(startIndex + PAGE_SIZE, chars.length)
  const pageChars = chars.slice(startIndex, endIndex)

  // 创建结果数组
  const result = [...pageChars]
  // 如果不足PAGE_SIZE，添加空占位符
  while (result.length < PAGE_SIZE) {
    result.push({
      id: `empty-${result.length}`,
      empty: true,
      content: "",
      position: result.length + 1,
    })
  }
  return result
}

// 竖排分组（横向优先的数组，分成8列6行，右起为第0列）
function groupCharsByColumn(chars: any[], columns = 8, rows = 6) {
  const result: any[][] = Array.from({ length: columns }, () => [])
  for (let col = 0; col < columns; col++) {
    for (let row = 0; row < rows; row++) {
      const idx = row * columns + col
      result[columns - 1 - col][row] = chars[idx]
    }
  }
  return result
}

// 空白占位符统一样式函数 - 确保与非空字符样式保持一致性
const renderEmptyPlaceholder = (flatIndex: number, colCount: number = 10) => {
  // 根据列数设置字符格子大小
  let cellSize;
  let textSize;

  if (colCount <= 3) {
    // 手机
    cellSize = "w-14 h-14";
    textSize = "text-base";
  } else if (colCount <= 5) {
    // 手机
    cellSize = "w-14 h-14";
    textSize = "text-xs";
  } else if (colCount <= 8) {
    // 平板
    cellSize = "w-14 h-14";
    textSize = "text-sm";
  } else {
    // 电脑，调整为更大尺寸
    cellSize = "w-14 h-14";
    textSize = "text-base";
  }

  // 与非空字符使用完全相同的容器样式
  return (
    <div
      key={`empty-${flatIndex}`}
      className={`border border-amber-brown/30 bg-ancient-card/80 font-medium relative ${cellSize} flex items-center justify-center`}
    >
      <div className="relative w-full h-full flex items-center justify-center">
        <span className={`text-amber-brown/40 ${textSize}`}>{flatIndex + 1}</span>
      </div>
    </div>
  )
}

// Utility function to safely construct image URLs
const getSafeImageUrl = (url: string | undefined, type: "original" | "typeset"): string => {
  if (!url) {
    return type === "original" ? "/images/origin01.png" : "/images/final01.png"
  }

  if (url.startsWith("http")) {
    return url
  }

  if (url.startsWith("/")) {
    return `${BASE_URL}${url}`
  }

  return `${BASE_URL}/${url}`
}

// 获取校对文字符的API
async function getTypesetChars(yeId: string) {
  try {
    const response = await axios.get(`${BASE_URL}/jiaodui/task-chars/jiaodui`, {
      params: { taskNum: Number(yeId) },
      timeout: 30000,
    });
    if (response.data && response.data.code === 200) {
      return Array.isArray(response.data.data) ? response.data.data : [];
    }
    return [];
  } catch (error: any) {
    return Array.from({ length: 100 }, (_, i) => ({
      id: `typeset-${i}`,
      content: `字${i + 1}`,
      position: i,
      ziUrl: "/images/final01.png"
    }));
  }
}

export default function ProofreadPage() {
  const router = useRouter()
  const userinfoRef = useRef<any>(null);
  const toolRef = useRef<any>(null);
  const [originalChars, setOriginalChars] = useState<Char[]>([])
  const [typesetChars, setTypesetChars] = useState<Char[]>([])
  const [confirmedChars, setConfirmedChars] = useState<Record<string, any>>({})
  const [currentOriginalIndex, setCurrentOriginalIndex] = useState(0)
  const [currentTypesetIndex, setCurrentTypesetIndex] = useState(0)
  const [totalChars, setTotalChars] = useState(0)
  const [completedChars, setCompletedChars] = useState(0) // 初始进度为0
  const [originalReadingMode, setOriginalReadingMode] = useState<"ancient" | "modern">("ancient")
  const [typesetReadingMode, setTypesetReadingMode] = useState<"ancient" | "modern">("ancient")
  const [operationHistory, setOperationHistory] = useState<any[]>([])
  const [showHistory, setShowHistory] = useState(false)
  const [longPressTimer, setLongPressTimer] = useState<NodeJS.Timeout | null>(null)
  const [columnCount, setColumnCount] = useState(5) // 默认列数
  const [showFinalDraft, setShowFinalDraft] = useState(false) // 终稿显示模式
  const { isVerticalLayout, setIsVerticalLayout } = useAppStore((state) => state);

  // 欢迎页面相关状态
  const [showWelcome, setShowWelcome] = useState(true)
  const [taskCode, setTaskCode] = useState("")
  const [isValidating, setIsValidating] = useState(false)
  const [validationError, setValidationError] = useState("")
  const [taskYeId, setTaskYeId] = useState("")

  // 在其他状态声明后添加
  const [isMobile, setIsMobile] = useState(false)

  // 去除模式相关状态
  const [isRemoveMode, setIsRemoveMode] = useState(false)
  const [selectedForRemoval, setSelectedForRemoval] = useState<number[]>([])
  const [afterRemoval, setAfterRemoval] = useState<number[]>([])

  // 放大查看模式相关状态
  const [isMagnifyMode, setIsMagnifyMode] = useState(false)
  const [selectedCharForMagnify, setSelectedCharForMagnify] = useState<{
    type: "original" | "typeset"
    index: number
    content: string
    position: number
    imageUrl?: string
  } | null>(null)
  const [showMagnifyPopup, setShowMagnifyPopup] = useState(false)

  // 分页相关状态
  const [currentOriginalPage, setCurrentOriginalPage] = useState(1)
  const [currentTypesetPage, setCurrentTypesetPage] = useState(1)
  const [charsPerPage, setCharsPerPage] = useState(0)
  const [totalOriginalPages, setTotalOriginalPages] = useState(1)
  const [totalTypesetPages, setTotalTypesetPages] = useState(1)

  // 手动链接状态
  const [isManualLinking, setIsManualLinking] = useState(false)
  const [manualLinkStep, setManualLinkStep] = useState(0) // 0: 未开始, 1: 已选择原文字符, 2: 已完成链接
  const [selectedOriginalIndex, setSelectedOriginalIndex] = useState(null)

  // 添加确认对话框状态
  const [showConfirmDialog, setShowConfirmDialog] = useState(false)
  const [confirmAction, setConfirmAction] = useState<(() => void) | null>(null)
  const [confirmMessage, setConfirmMessage] = useState("")

  // 项目信息
  const projectInfo = {
    name: "《般若波罗蜜多心经》校对",
    totalPages: 108,
    currentPage: 42,
    taskId: "BNJ-22-05",
  }

  // 引用当前字符的元素
  const currentOriginalRef = useRef<HTMLDivElement>(null)
  const currentTypesetRef = useRef<HTMLDivElement>(null)

  // 容器引用
  const originalContainerRef = useRef<HTMLDivElement>(null)
  const typesetContainerRef = useRef<HTMLDivElement>(null)
  const undoButtonRef = useRef<HTMLButtonElement>(null)

  const [yeId, setYeId] = useState("")
  const [chars, setChars] = useState<any[]>([])
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState("")

  // 处理任务代码验证
  const handleTaskCodeSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    setIsValidating(true)
    setValidationError("")

    try {
      const result = await validateTaskCode(taskCode)
      if (result.success) {
        setTaskYeId(result.yeId)
        setShowWelcome(false)
        // 验证成功后直接加载数据
        loadData(result.yeId)
      } else {
        setValidationError(result.message)
      }
    } catch (error) {
      setValidationError("验证失败，请稍后重试")
    } finally {
      setIsValidating(false)
    }
  }

  // 加载数据函数
  const loadData = async (yeId: string) => {
    try {
      setLoading(true)

      // 加载原文字符
      const originalData = await getOriginalChars(yeId)
      const arr = Array.isArray(originalData) ? originalData : []
      setOriginalChars(arr)
      setTotalChars(arr.length)
      setCurrentOriginalIndex(0)

      // 加载校对字符
      const typesetData = await getTypesetChars(yeId)
      const typeArr = Array.isArray(typesetData) ? typesetData : []
      setTypesetChars(typeArr)
    } catch (error) {
      setError("加载数据失败，请稍后重试")
    } finally {
      setLoading(false)
    }
  }

  // 计算自适应列数和每页字符数
  useEffect(() => {
    const calculateColumnsAndPages = () => {
      // 根据屏幕宽度自适应列数
      // let columns = DESKTOP_COLUMNS; // 默认电脑端10列
      const screenWidth = window.innerWidth;
      const baseFontSize = parseInt(window.getComputedStyle(document.documentElement).fontSize)
      const itemSize = baseFontSize * 3.5
      const rowNum = ~~((window.innerHeight - userinfoRef.current?.clientHeight - toolRef.current?.clientHeight - 60) / (itemSize + baseFontSize * 0.75))
      const columns = ~~((window.innerWidth / 2 - 2 * baseFontSize) / (itemSize + baseFontSize * 0.25))
      // if (screenWidth < 480) {
      //   // 手机屏幕
      //   columns = 3
      // } else if (screenWidth < 640) {
      //   // 手机屏幕
      //   columns = MOBILE_COLUMNS;
      // } else if (screenWidth < 1024) {
      //   // 平板屏幕
      //   columns = TABLET_COLUMNS;
      // }

      PAGE_SIZE = columns * rowNum
      // 根据列数计算行数（确保总数为100个字符）
      const rows = Math.ceil(PAGE_SIZE / columns);
      const charsPerPageCount = columns * rows;

      setColumnCount(columns);
      setCharsPerPage(charsPerPageCount);

      // 计算总页数
      if (originalChars.length > 0) {
        setTotalOriginalPages(Math.ceil(originalChars.length / charsPerPageCount));
      }
      if (typesetChars.length > 0) {
        setTotalTypesetPages(Math.ceil(typesetChars.length / charsPerPageCount));
      }
    };

    calculateColumnsAndPages();
    window.addEventListener("resize", calculateColumnsAndPages);

    return () => {
      window.removeEventListener("resize", calculateColumnsAndPages);
    };
  }, [originalChars.length, typesetChars.length, isVerticalLayout]);

  // 检测移动设备
  useEffect(() => {
    const checkMobile = () => {
      const mobile = window.innerWidth < 768
      setIsMobile(mobile)
      // setIsVerticalLayout(mobile)
    }

    checkMobile()
    window.addEventListener("resize", checkMobile)

    return () => {
      window.removeEventListener("resize", checkMobile)
    }
  }, [])

  // 当当前索引变化时，更新页码
  useEffect(() => {
    if (charsPerPage > 0) {
      // 计算当前字符应该在哪一页
      const originalPage = Math.floor(currentOriginalIndex / charsPerPage) + 1
      const typesetPage = Math.floor(currentTypesetIndex / charsPerPage) + 1
      // 更新页码
      setCurrentOriginalPage(originalPage)
      setCurrentTypesetPage(typesetPage)
    }
  }, [currentOriginalIndex, currentTypesetIndex, charsPerPage])

  // 添加操作到历史记录
  const addToHistory = (operation: any) => {
    const timestamp = new Date().toLocaleTimeString()
    const uniqueId = `op-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
    setOperationHistory((prev) => [{ ...operation, timestamp, id: uniqueId }, ...prev])
  }

  // 确认当前字符
  const confirmChar = () => {
    setConfirmedChars((prev: any) => {
      const updated = { ...prev }
      // 使用映射键来存储原文和校对字符的对应关系
      const mappingKey = `map-${currentOriginalIndex}-${currentTypesetIndex}`
      updated[mappingKey] = {
        status: "confirmed",
        originalIndex: currentOriginalIndex,
        typesetIndex: currentTypesetIndex,
      }
      return updated
    })

    // 同时移动原文和校对的光标
    let nextOriginalIndex = currentOriginalIndex + 1

    // 跳过被标记为非正文的字符
    while (nextOriginalIndex < originalChars.length && confirmedChars[`remove-${nextOriginalIndex}`]) {
      nextOriginalIndex++
    }

    setCurrentOriginalIndex(nextOriginalIndex)
    setCurrentTypesetIndex((prev) => prev + 1)
    setCompletedChars((prev) => Math.min(prev + 1, totalChars))

    // 添加到历史记录
    addToHistory({
      type: "confirm",
      originalIndex: currentOriginalIndex,
      typesetIndex: currentTypesetIndex,
      originalContent: originalChars[currentOriginalIndex]?.content || "",
      typesetContent: typesetChars[currentTypesetIndex]?.content || "",
      description: `确认对应: ${originalChars[currentOriginalIndex]?.content || ""} ↔ ${typesetChars[currentTypesetIndex]?.content || ""}`,
    })
  }

  // 标记字符有问题
  const markCharProblem = () => {
    setConfirmedChars((prev: any) => {
      const updated = { ...prev }
      // 使用映射键来存储原文和校对字符的对应关系
      const mappingKey = `map-${currentOriginalIndex}-${currentTypesetIndex}`
      updated[mappingKey] = {
        status: "problem",
        originalIndex: currentOriginalIndex,
        typesetIndex: currentTypesetIndex,
      }
      return updated
    })

    // 同时移动原文和校对的光标
    let nextOriginalIndex = currentOriginalIndex + 1

    // 跳过被标记为非正文的字符
    while (nextOriginalIndex < originalChars.length && confirmedChars[`remove-${nextOriginalIndex}`]) {
      nextOriginalIndex++
    }

    setCurrentOriginalIndex(nextOriginalIndex)
    setCurrentTypesetIndex((prev) => prev + 1)
    setCompletedChars((prev) => Math.min(prev + 1, totalChars))

    // 添加到历史记录
    addToHistory({
      type: "problem",
      originalIndex: currentOriginalIndex,
      typesetIndex: currentTypesetIndex,
      originalContent: originalChars[currentOriginalIndex]?.content || "",
      typesetContent: typesetChars[currentTypesetIndex]?.content || "",
      description: `标记问题: ${originalChars[currentOriginalIndex]?.content || ""} ↔ ${typesetChars[currentTypesetIndex]?.content || ""}`,
    })
  }

  // 跳过当前字符（排版多字）
  const skipChar = () => {
    // 只标记排版字符为已跳过，不影响原文字符
    const updatedTypesetChars = [...typesetChars]
    if (updatedTypesetChars[currentTypesetIndex]) {
      updatedTypesetChars[currentTypesetIndex] = {
        ...updatedTypesetChars[currentTypesetIndex],
        skipped: true,
      }
    }
    setTypesetChars(updatedTypesetChars)

    // 记录跳过状态
    setConfirmedChars((prev: any) => {
      const updated = { ...prev }
      updated[`skip-${currentTypesetIndex}`] = {
        status: "skipped",
        typesetIndex: currentTypesetIndex,
      }
      return updated
    })

    // 只移动校对的光标，原文光标不变
    setCurrentTypesetIndex((prev) => prev + 1)
    setCompletedChars((prev) => Math.min(prev + 1, totalChars))

    // 添加到历史记录
    addToHistory({
      type: "skip",
      originalIndex: currentOriginalIndex, // 原文索引不变
      typesetIndex: currentTypesetIndex,
      typesetContent: typesetChars[currentTypesetIndex]?.content || "",
      description: `跳过字符: ${typesetChars[currentTypesetIndex]?.content || ""}`,
    })
  }

  // 插入字符（排版少字）
  const insertChar = () => {
    // 获取前一个字符的编号
    const prevIndex = Math.max(0, currentTypesetIndex - 1)
    const prevNumber = prevIndex + 1

    // 计算插入的字符编号
    const insertedCharsAtPosition = typesetChars.filter((char) => char.insertedAfter === prevNumber).length
    const insertNumber = insertedCharsAtPosition + 1

    // 创建新字符
    const newChar = {
      id: `insert-${prevNumber}-${insertNumber}-${Date.now()}`,
      content: `排字${prevNumber}-${insertNumber}`,
      position: currentTypesetIndex,
      inserted: true,
      insertedAfter: prevNumber,
    }

    // 插入新字符
    const updatedTypesetChars = [...typesetChars]
    updatedTypesetChars.splice(currentTypesetIndex, 0, newChar)
    setTypesetChars(updatedTypesetChars)

    // 标记为已插入
    setConfirmedChars((prev: any) => {
      const updated = { ...prev }
      updated[`insert-${currentTypesetIndex}-${Date.now()}`] = {
        status: "inserted",
        typesetIndex: currentTypesetIndex,
        char: newChar,
      }
      return updated
    })

    // 不移动当前索引，因为我们刚刚在当前位置插入了一个新字符
    setCompletedChars((prev) => Math.min(prev + 1, totalChars))

    // 添加到历史记录
    addToHistory({
      type: "insert",
      originalIndex: currentOriginalIndex,
      typesetIndex: currentTypesetIndex,
      charContent: newChar.content,
      description: `插入字符: ${newChar.content}`,
    })

    // 更新总页数
    if (charsPerPage > 0) {
      setTotalTypesetPages(Math.ceil((typesetChars.length + 1) / charsPerPage))
    }
  }

  // 撤销上一步操作
  const undoLastOperation = () => {
    if (operationHistory.length === 0) return

    const lastOperation = operationHistory[0]
    console.log(operationHistory)

    // 根据操作类型执行撤销
    switch (lastOperation.type) {
      case "confirm":
      case "problem":
        // 移除确认状态
        setConfirmedChars((prev) => {
          const updated = { ...prev }
          const mappingKey = `map-${lastOperation.originalIndex}-${lastOperation.typesetIndex}`
          delete updated[mappingKey]
          return updated
        })

        // 移动索引回到上一个位置
        setCurrentOriginalIndex(lastOperation.originalIndex)
        setCurrentTypesetIndex(lastOperation.typesetIndex)
        setCompletedChars((prev) => Math.max(0, prev - 1))
        break

      case "skip":
        // 移除跳过状态
        setConfirmedChars((prev) => {
          const updated = { ...prev }
          delete updated[`skip-${lastOperation.typesetIndex}`]
          return updated
        })

        // 恢复字符状态
        setTypesetChars((prev) => {
          const updated = [...prev]
          if (updated[lastOperation.typesetIndex]) {
            updated[lastOperation.typesetIndex] = {
              ...updated[lastOperation.typesetIndex],
              skipped: false,
            }
          }
          return updated
        })

        // 移动校对索引回到上一个位置，原文索引不变
        setCurrentTypesetIndex(lastOperation.typesetIndex)
        setCompletedChars((prev) => Math.max(0, prev - 1))
        break

      case "insert":
        // 移除插入的字符
        setTypesetChars((prev) => {
          const updated = [...prev]
          const insertIndex = updated.findIndex((char) => char.content === lastOperation.charContent && char.inserted)
          if (insertIndex !== -1) {
            updated.splice(insertIndex, 1)
          }
          return updated
        })

        // 移除插入记录
        setConfirmedChars((prev) => {
          const updated = { ...prev }
          // 查找并删除相关的插入记录
          Object.keys(updated).forEach((key) => {
            if (
              key.startsWith("insert-") &&
              updated[key].typesetIndex === lastOperation.typesetIndex &&
              updated[key].char?.content === lastOperation.charContent
            ) {
              delete updated[key]
            }
          })
          return updated
        })

        setCompletedChars((prev) => Math.max(0, prev - 1))

        // 更新总页数
        if (charsPerPage > 0) {
          setTotalTypesetPages(Math.ceil((typesetChars.length - 1) / charsPerPage))
        }
        break

      case "undo":
        // 如果是撤销操作，我们需要恢复被撤销的操作
        // 这部分逻辑比较复杂，暂不实现
        break
      case "manual-link":
        // 移除手动链接状态
        setConfirmedChars((prev) => {
          const updated = { ...prev }
          const mappingKey = `map-${lastOperation.originalIndex}-${lastOperation.typesetIndex}`
          delete updated[mappingKey]
          return updated
        })

        // 减少完成字符数
        setCompletedChars((prev) => Math.max(0, prev - 1))
        break
      case "remove-origin":
        // 移除去除状态
        setConfirmedChars((prev) => {
          const updated = { ...prev }
          lastOperation.list.forEach((v: number) => {
            delete updated[`remove-origin-${v}`]
          })
          return updated
        })

        // 移动索引回到上一个位置
        // setCurrentOriginalIndex(lastOperation.originalIndex)
        setCompletedChars((prev) => Math.max(0, prev - 1))
        break
      case "remove-after":
        // 移除去除状态
        setConfirmedChars((prev) => {
          const updated = { ...prev }
          lastOperation.list.forEach((v: number) => {
            delete updated[`remove-after-${v}`]
          })
          return updated
        })

        // 移动索引回到上一个位置
        // setCurrentTypesetIndex(lastOperation.originalIndex)
        setCompletedChars((prev) => Math.max(0, prev - 1))
        break
    }

    // 从历史记录中移除该操作
    setOperationHistory((prev) => prev.slice(1))

    // 不再添加撤销操作到历史记录，这样就不会干扰连续撤销
    // 原来的代码会将每次撤销也记录到历史中，导致无法连续撤销
    // addToHistory({
    //   type: "undo",
    //   undoneOperation: lastOperation,
    //   description: `撤销: ${lastOperation.description}`,
    // })
  }

  // 切换阅读模式
  const toggleReadingMode = (target: "original" | "typeset") => {
    if (target === "original") {
      const newMode = originalReadingMode === "ancient" ? "modern" : "ancient"
      setOriginalReadingMode(newMode)
    } else {
      const newMode = typesetReadingMode === "ancient" ? "modern" : "ancient"
      setTypesetReadingMode(newMode)
    }

    // 强制重新渲染，确保布局更新
    setTimeout(() => {
      window.dispatchEvent(new Event("resize"))
    }, 10)
  }

  // 切换终稿显示模式
  const toggleFinalDraft = () => {
    setShowFinalDraft((prev) => !prev)
  }

  // 翻页函数 - 同时翻页，但保持当前选中的字符不变
  const goToNextPage = () => {
    if (currentOriginalPage < totalOriginalPages || currentTypesetPage < totalTypesetPages) {
      // 更新页码
      setCurrentOriginalPage(currentOriginalPage + 1)
      setCurrentTypesetPage(currentTypesetPage + 1)

      // 不改变当前选中的字符索引
      // 只更新页面显示
    }
  }

  const goToPrevPage = () => {
    if (currentOriginalPage > 1 || currentTypesetPage > 1) {
      // 更新页码
      setCurrentOriginalPage(Math.max(currentOriginalPage - 1, 1))
      setCurrentTypesetPage(Math.max(currentTypesetPage - 1, 1))

      // 不改变当前选中的字符索引
      // 只更新页面显示
    }
  }

  // 处理撤销按钮长按
  const handleUndoButtonMouseDown = () => {
    const timer = setTimeout(() => {
      setShowHistory(true)
    }, 500)
    setLongPressTimer(timer)
  }

  const handleUndoButtonMouseUp = () => {
    if (longPressTimer) {
      clearTimeout(longPressTimer)
      setLongPressTimer(null)
    }
  }

  // 处理撤销按钮右键点击
  const handleUndoButtonContextMenu = (e: any) => {
    e.preventDefault()
    setShowHistory(true)
  }

  // 关闭历史记录窗口
  const closeHistoryWindow = () => {
    setShowHistory(false)
  }

  // 计算项目进度百分比
  const projectProgressPercentage = Math.floor((projectInfo.currentPage / projectInfo.totalPages) * 100)

  // 计算当前任务进度百分比
  const progressPercentage = totalChars > 0 ? Math.floor((completedChars / totalChars) * 100) : 0

  // 获取字符的阅读顺序索引
  const getReadingOrderIndex = (index: number, totalChars: number, columns: number, mode: string) => {
    const rows = Math.ceil(totalChars / columns)
    if (mode === "modern") {
      // 现代文：从上到下，从左往右
      return (index % rows) + Math.floor(index / rows) * rows
    } else {
      // 古文：从上到下，从右往左，编号1在右上角
      return (index % rows) + (columns - 1 - Math.floor(index / rows)) * rows
    }
  }

  // 检查字符是否被确认
  const isCharConfirmed = (originalIndex: any, typesetIndex: any) => {
    // 检查是否有对应关系
    const mappingKey = `map-${originalIndex}-${typesetIndex}`
    return confirmedChars[mappingKey] !== undefined
  }

  // 获取字符的确认状态
  const getCharConfirmStatus = (originalIndex: any, typesetIndex: any) => {
    const mappingKey = `map-${originalIndex}-${typesetIndex}`
    return confirmedChars[mappingKey]?.status
  }

  // 检查排版字符是否被跳过
  const isTypesetCharSkipped = (index: any) => {
    return confirmedChars[`skip-${index}`] !== undefined || typesetChars[index]?.skipped
  }

  // 获取终稿模式下显示的字符
  const getFinalDraftChars = () => {
    if (!showFinalDraft) return typesetChars

    // 在终稿模式下，过滤掉跳过的字符，包含插入的字符
    return typesetChars.filter((char) => !char.skipped)
  }

  // 获取当前页的字符
  const getCurrentPageChars = (chars: any, currentPage: number) => {
    if (!Array.isArray(chars) || charsPerPage <= 0) return []
    const startIndex = (currentPage - 1) * charsPerPage
    const endIndex = startIndex + charsPerPage
    return chars.slice(startIndex, endIndex)
  }

  // 开始手动链接过程
  const startManualLinking = () => {
    setIsMagnifyMode(false)
    setIsRemoveMode(false)
    setIsManualLinking(true)
    setManualLinkStep(0)
    setSelectedOriginalIndex(null)
  }

  // 开始放大查看模式
  const startMagnifyMode = () => {
    setIsMagnifyMode(true)
    setSelectedCharForMagnify(null)
    setShowMagnifyPopup(false)
  }

  // 关闭放大弹窗
  const closeMagnifyPopup = () => {
    setShowMagnifyPopup(false)
  }

  // 处理字符点击事件
  const handleCharClick = async (type: any, index: any) => {
    if (isRemoveMode) {
      // Handle remove mode selection
      if (type === 'original') {
        if (afterRemoval.length) return toast({ title: '请先确认删除校对文' })
        setSelectedForRemoval((prev) => {
          if (prev.includes(index)) {
            // If already selected, deselect it
            return prev.filter((i) => i !== index)
          } else {
            // Otherwise add to selection
            return [...prev, index]
          }
        })
      } else {
        if (selectedForRemoval.length) return toast({ title: '请先确认删除原文' })
        setAfterRemoval((prev) => {
          if (prev.includes(index)) {
            // If already selected, deselect it
            return prev.filter((i) => i !== index)
          } else {
            // Otherwise add to selection
            return [...prev, index]
          }
        })
      }
      return
    }

    if (isMagnifyMode) {
      // 获取字符信息
      const charArray = type === "original" ? originalChars : typesetChars
      const char = charArray[index]
      const res = await getCharDetail(char.id)
      if (res) {
        setSelectedCharForMagnify(res)
        setShowMagnifyPopup(true)
        setIsMagnifyMode(false) // 选择后退出放大模式
      }
      return
    }

    if (!isManualLinking) return

    if (type === "original" && manualLinkStep === 0) {
      // 第一步：选择原文字符
      setSelectedOriginalIndex(index)
      setManualLinkStep(1)
    } else if (type === "typeset" && manualLinkStep === 1 && selectedOriginalIndex !== null) {
      // 第二步：选择校对字符并创建链接
      setConfirmedChars((prev) => {
        const updated = { ...prev }
        // 使用映射键来存储原文和校对字符的对应关系
        const mappingKey = `map-${selectedOriginalIndex}-${index}`
        updated[mappingKey] = {
          status: "confirmed",
          originalIndex: selectedOriginalIndex,
          typesetIndex: index,
        }
        return updated
      })

      // 添加到历史记录
      addToHistory({
        type: "manual-link",
        originalIndex: selectedOriginalIndex,
        typesetIndex: index,
        originalContent: originalChars[selectedOriginalIndex]?.content || "",
        typesetContent: typesetChars[index]?.content || "",
        description: `手动链接: ${originalChars[selectedOriginalIndex]?.content || ""} ↔ ${typesetChars[index]?.content || ""}`,
      })

      // 重置手动链接状态
      setIsManualLinking(false)
      setManualLinkStep(0)
      setSelectedOriginalIndex(null)

      // 更新完成字符数
      setCompletedChars((prev) => Math.min(prev + 1, totalChars))
    }
  }

  // 辅助函数：渲染编号，统一现代文和古文模式下的样式
  const renderNumber = (num: number, mode: "ancient" | "modern" = "modern") => {
    // 添加空值检查，防止null或undefined导致toString错误
    if (num === null || num === undefined) {
      return null;
    }
    
    const str = num.toString();

    // 统一使用横排显示数字，不再根据模式区分
    const commonClasses = "proofread-number absolute bottom-0 right-0 bg-ancient-scroll/70 rounded-sm px-1 text-xs"

    // 使用完全相同的样式，不区分古文和现代文模式
    return (
      <span className={commonClasses} style={{ letterSpacing: 0 }}>
        {str.split("").map((s, i) => (
          <span key={i}>{s}</span>
        ))}
      </span>
    )
  }

  // 渲染原文字符
  const renderOriginalChars = () => {
    const columns = columnCount;
    const rows = Math.ceil(PAGE_SIZE / columns);

    // 确保有字符数据
    if (originalChars.length === 0) {
      return (
        <div className="flex items-center justify-center h-full">
          <p className="text-amber-brown">正在加载数据...</p>
        </div>
      );
    }

    // 获取当前页的字符
    let pageChars = getCurrentPageCharsWithPadding(originalChars.filter((v, i) => !confirmedChars[`remove-origin-${i}`]), currentOriginalPage).filter((v, i) => !selectedForRemoval.includes(i));
    return renderCharGrid(
      pageChars,
      originalChars,
      originalReadingMode,
      "original",
      currentOriginalIndex,
      selectedOriginalIndex,
    );
  };

  // 渲染校对字符
  const renderTypesetChars = () => {
    const columns = columnCount;
    const rows = Math.ceil(PAGE_SIZE / columns);

    // 确保有字符数据
    if (typesetChars.length === 0) {
      return (
        <div className="flex items-center justify-center h-full">
          <p className="text-amber-brown">正在加载数据...</p>
        </div>
      );
    }

    const allCharsToRender = showFinalDraft ? getFinalDraftChars() : typesetChars;
    // 获取当前页的字符
    let pageChars = getCurrentPageCharsWithPadding(allCharsToRender.filter((v, i) => !confirmedChars[`remove-after-${i}`]), currentTypesetPage).filter((v, i) => !afterRemoval.includes(i));

    return renderCharGrid(pageChars, typesetChars, typesetReadingMode, "typeset", currentTypesetIndex, null);
  };

  // 统一的字符网格渲染函数
  const renderCharGrid = (
    pageChars: any[],
    originalSource: any[],
    mode: "ancient" | "modern",
    type: "original" | "typeset",
    currentIdx: number,
    selectedIdx: any,
  ) => {
    const columns = columnCount;
    const rows = Math.ceil(PAGE_SIZE / columns);

    // 按照现代文的样式统一设置布局类
    const containerClasses = "flex justify-center items-center h-full w-full p-1 overflow-hidden";
    
    // 根据列数调整间距
    let gapClasses: any;
    if (columnCount <= 5) {
      // 手机 - 较小间距
      gapClasses = "gap-1.5";
    } else if (columnCount <= 8) {
      // 平板 - 中等间距
      gapClasses = "gap-2";
    } else {
      // 电脑 - 较大间距
      gapClasses = "gap-2.5";
    }

    if (mode === "ancient") {
      // 古文模式 - 仍然保持竖排从右到左的阅读顺序，但使用与现代文相同的网格布局
      return (
        <div className={`${containerClasses} flex-col ${gapClasses}`}>
          {/* 像现代文一样创建10行 */}
          {Array.from({ length: rows }).map((_, rowIndex) => (
            <div key={`row-${rowIndex}`} className={`flex flex-row ${gapClasses} w-full justify-center`}>
              {/* 像现代文一样每行10列，但从右到左填充 */}
              {Array.from({ length: columns }).map((_, colIndex) => {
                // 古文模式下，我们从右到左填充，所以反转列索引
                const reversedColIndex = columns - 1 - colIndex

                // 计算在古文阅读顺序下的索引（右起，先上后下）
                // 要查找到的字符索引需要考虑阅读顺序
                const ancientReadingIndex = reversedColIndex * rows + rowIndex

                // 获取字符，确保安全访问
                const char =
                  ancientReadingIndex < pageChars.length
                    ? pageChars[ancientReadingIndex]
                    : {
                        empty: true,
                        id: `empty-${ancientReadingIndex}`,
                        content: "",
                        position: ancientReadingIndex + 1,
                      }

                return renderCharCell(char, ancientReadingIndex, originalSource, type, mode, currentIdx, selectedIdx)
              })}
            </div>
          ))}
        </div>
      )
    } else {
      // 现代文模式：横排从左到右
      return (
        <div className={`${containerClasses} flex-col ${gapClasses}`}>
          {/* 创建10行 */}
          {Array.from({ length: rows }).map((_, rowIndex) => (
            <div key={`row-${rowIndex}`} className={`flex flex-row ${gapClasses} w-full justify-center`}>
              {/* 每行10列 */}
              {Array.from({ length: columns }).map((_, colIndex) => {
                // 计算索引 - 现代文模式列优先索引
                const flatIndex = rowIndex * columns + colIndex

                // 获取字符，确保安全访问
                const char =
                  flatIndex < pageChars.length
                    ? pageChars[flatIndex]
                    : {
                        empty: true,
                        id: `empty-${flatIndex}`,
                        content: "",
                        position: flatIndex + 1,
                      }

                return renderCharCell(char, flatIndex, originalSource, type, mode, currentIdx, selectedIdx)
              })}
            </div>
          ))}
        </div>
      )
    }
  }

  // 单个字符单元格渲染 - 统一古文和现代文的字符显示样式
  const renderCharCell = (
    char: any,
    flatIndex: number,
    originalSource: any[],
    type: "original" | "typeset",
    mode: "ancient" | "modern",
    currentIdx: number,
    selectedIdx: any,
  ) => {
    if (char.empty) {
      return renderEmptyPlaceholder(flatIndex, columnCount)
    }

    const actualIndex = originalSource.findIndex((c) => c.id === char.id)
    const isCurrentChar = actualIndex === currentIdx && (type === "typeset" ? !showFinalDraft : true)

    let correspondingIndex, hasConfirmedMatch, confirmStatus

    if (type === "original") {
      correspondingIndex = Object.keys(confirmedChars)
        .filter((key) => key.startsWith("map-"))
        .find((key) => {
          const [_, origIdx, typeIdx] = key.split("-")
          return Number.parseInt(origIdx) === actualIndex
        })
        ?.split("-")[2]
      hasConfirmedMatch = correspondingIndex !== undefined
      confirmStatus = hasConfirmedMatch ? confirmedChars[`map-${actualIndex}-${correspondingIndex}`]?.status : null
    } else {
      correspondingIndex = Object.keys(confirmedChars)
        .filter((key) => key.startsWith("map-"))
        .find((key) => {
          const [_, origIdx, typeIdx] = key.split("-")
          return Number.parseInt(typeIdx) === actualIndex
        })
        ?.split("-")[1]
      hasConfirmedMatch = correspondingIndex !== undefined
      confirmStatus = hasConfirmedMatch ? confirmedChars[`map-${correspondingIndex}-${actualIndex}`]?.status : null

      // 校对特有的状态
      const isSkipped = isTypesetCharSkipped(actualIndex)
      if (showFinalDraft && isSkipped) return null
    }

    const isSelected = type === "original" && selectedIdx === actualIndex
    const isManualLinkingActive = type === "original" ? isManualLinking : isManualLinking && manualLinkStep === 1

    // Check if this character is selected for removal
    const isSelectedForRemoval = type === "original" && isRemoveMode && selectedForRemoval.includes(actualIndex)

    // Add classes for removed and selected for removal states
    const additionalClasses = `
      ${isSelectedForRemoval ? "ring-2 ring-purple-500 bg-purple-100/50" : ""}
      ${isRemoveMode && type === "original" ? "cursor-pointer hover:bg-purple-100/30" : ""}
    `

    // 根据列数设置字符格子大小
    let cellSize;
    let textSize;

    if (columnCount <= 3) {
      // 手机
      cellSize = "w-14 h-14";
      textSize = "text-base";
    } else if (columnCount <= 5) {
      // 手机
      cellSize = "w-14 h-14";
      textSize = "text-base";
    } else if (columnCount <= 8) {
      // 平板
      cellSize = "w-14 h-14";
      textSize = "text-lg";
    } else {
      // 电脑，增大尺寸
      cellSize = "w-14 h-14";
      textSize = "text-xl";
    }

    // 在renderCharCell函数中，修改字符单元格的样式类
    const commonClassNames = `border border-amber-brown/30 bg-ancient-card/80 font-medium relative ${cellSize}
          ${isCurrentChar ? "ring-2 ring-amber-brown bg-amber-brown/20" : ""}
          ${isSelected ? "ring-2 ring-blue-500 bg-blue-100/20" : ""} 
          ${isManualLinkingActive ? "cursor-pointer hover:bg-amber-brown/10" : ""}
          ${type === "typeset" && char.skipped ? "opacity-50" : ""}
          ${type === "typeset" && char.inserted ? "border-purple-500 border-2" : ""}
          ${additionalClasses}
          `

    // 统一的样式类，无论古文还是现代文模式
    const commonStyles = {
      display: "flex",
      alignItems: "center",
      justifyContent: "center",
      position: "relative" as const,
      overflow: "hidden",
    }

    return (
      <div
        key={char.id}
        ref={isCurrentChar ? (type === "original" ? currentOriginalRef : currentTypesetRef) : null}
        className={commonClassNames}
        style={commonStyles}
        onClick={() => handleCharClick(type, actualIndex)}
      >
        {hasConfirmedMatch && (
          <div
            className={`absolute inset-0 ${confirmStatus === "problem" ? "bg-red-500/30" : "bg-green-500/30"} flex items-center justify-center`}
          >
            {confirmStatus === "confirmed" && <CheckCircle className="h-6 w-6 text-green-700" />}
            {confirmStatus === "problem" && <HelpCircle className="h-6 w-6 text-red-600" />}
          </div>
        )}
        {type === "typeset" && isTypesetCharSkipped(actualIndex) && !showFinalDraft && (
          <div className="absolute inset-0 bg-blue-500/30 flex items-center justify-center">
            <SkipForward className="h-6 w-6 text-blue-700" />
          </div>
        )}
        <div className="relative w-full h-full flex items-center justify-center">
          {char.ziUrl ? (
            <div className="relative w-full h-full">
              <img
                src={getSafeImageUrl(char.ziUrl, type) || "/placeholder.svg"}
                alt={char.content || `字符${char.position}`}
                className="w-full h-full max-w-full max-h-full object-contain p-1"
                style={{
                  aspectRatio: "1/1",
                  display: "block",
                  writingMode: mode === "ancient" ? "vertical-rl" : "horizontal-tb",
                }}
                onError={(e) => {
                  ;(e.target as HTMLImageElement).src =
                    type === "original" ? "/images/origin01.png" : "/images/final01.png"
                }}
              />
              {renderNumber(char.position)}
            </div>
          ) : (
            <div
              className={`relative w-full h-full flex items-center justify-center ${textSize}`}
              style={{ writingMode: mode === "ancient" ? "vertical-rl" : "horizontal-tb" }}
            >
              <span className="text-amber-brown">{char.content || `${char.position}`}</span>
              {renderNumber(char.position)}
            </div>
          )}
        </div>
      </div>
    )
  }

  // 新的渲染函数，根据模式直接在div中应用样式，避免使用通用函数
  const renderContent = (mode: "original" | "typeset") => {
    // 获取相应的阅读模式
    const readingMode = mode === "original" ? originalReadingMode : typesetReadingMode

    // 根据模式选择渲染函数
    if (mode === "original") {
      return renderOriginalChars()
    } else {
      return renderTypesetChars()
    }
  }

  // 添加处理返回按钮点击的函数
  const handleBackClick = () => {
    setConfirmMessage("确定要离开校对页面吗？未保存的进度将会丢失。")
    setConfirmAction(() => {
      router.push("/")
    })
    setShowConfirmDialog(true)
  }

  // 添加处理底部导航点击的函数
  const handleNavClick = (tab: any) => {
    setConfirmMessage("确定要离开校对页面吗？未保存的进度将会丢失。")
    setConfirmAction(() => {
      router.push(`/?tab=${tab}`)
    })
    setShowConfirmDialog(true)
  }

  // 添加确认对话框关闭函数
  const closeConfirmDialog = () => {
    setShowConfirmDialog(false)
    setConfirmAction(null)
  }

  // 添加执行确认操作的函数
  const executeConfirmAction = () => {
    if (confirmAction) {
      confirmAction()
    }
    closeConfirmDialog()
  }

  // 添加下面的useEffect来记录每页加载的字符

  useEffect(() => {
    // 在页面变化时记录字符信息
    if (originalChars.length > 0) {
      const startIndex = (currentOriginalPage - 1) * PAGE_SIZE
      const endIndex = Math.min(startIndex + PAGE_SIZE, originalChars.length)
    }
  }, [currentOriginalPage, originalChars, originalReadingMode])

  useEffect(() => {
    // 在页面变化时记录字符信息
    if (typesetChars.length > 0) {
      const startIndex = (currentTypesetPage - 1) * PAGE_SIZE
      const endIndex = Math.min(startIndex + PAGE_SIZE, typesetChars.length)
    }
  }, [currentTypesetPage, typesetChars, typesetReadingMode])

  // 渲染欢迎页面
  const renderWelcomePage = () => {
    return (
      <div className="min-h-screen bg-ancient-scroll font-ancient text-ancient-text flex flex-col">
        {/* 顶部导航栏 */}
        <div className="bg-ancient-card/90 backdrop-blur-sm border-b border-amber-brown/30 p-3">
          <div className="container mx-auto max-w-5xl">
            <div className="flex items-center justify-between">
              <div className="flex items-center gap-3">
                <Button
                  variant="ghost"
                  size="icon"
                  onClick={() => router.push("/")}
                  className="text-amber-brown hover:bg-amber-brown/10"
                  title="返回"
                >
                  <ArrowLeft className="h-5 w-5" />
                </Button>
                <h1 className="text-lg font-bold text-amber-brown">古籍校对系统</h1>
              </div>
            </div>
          </div>
        </div>

        {/* 欢迎内容 */}
        <div className="flex-1 flex items-center justify-center p-4">
          <div className="bg-ancient-card/90 backdrop-blur-sm rounded-lg border border-amber-brown/30 shadow-ancient max-w-md w-full p-6 md:p-8">
            <div className="text-center mb-6">
              <div className="flex justify-center mb-4">
                <div className="w-16 h-16 bg-amber-brown/20 rounded-full flex items-center justify-center">
                  <Lock className="h-8 w-8 text-amber-brown" />
                </div>
              </div>
              <h2 className="text-xl md:text-2xl font-bold text-amber-brown mb-2">欢迎进入校对系统</h2>
              <p className="text-ancient-text/70">请输入6位数字任务代码继续</p>
            </div>

            <form onSubmit={handleTaskCodeSubmit} className="space-y-4">
              <div className="space-y-2">
                <label htmlFor="taskCode" className="block text-sm font-medium text-ancient-text/80">
                  任务代码
                </label>
                <Input
                  id="taskCode"
                  type="text"
                  value={taskCode}
                  onChange={(e) => setTaskCode(e.target.value)}
                  placeholder="请输入6位数字任务代码"
                  className="bg-ancient-scroll/50 border-amber-brown/30 focus:border-amber-brown focus:ring-amber-brown"
                  maxLength={6}
                  pattern="\d{6}"
                  required
                />
                {validationError && (
                  <div className="flex items-center gap-1 text-red-600 text-sm mt-1">
                    <AlertCircle className="h-4 w-4" />
                    <span>{validationError}</span>
                  </div>
                )}
              </div>

              <Button
                type="submit"
                className="w-full bg-amber-brown hover:bg-amber-brown-dark text-ancient-scroll"
                disabled={isValidating || taskCode.length !== 6 || !/^\d{6}$/.test(taskCode)}
              >
                {isValidating ? "验证中..." : "开始校对"}
              </Button>
            </form>

            <div className="mt-6 text-center text-sm text-ancient-text/60">
              <p>任务代码由管理员分配，请妥善保管</p>
              <p className="mt-1">如有疑问，请联系管理员</p>
            </div>
          </div>
        </div>

        {/* 底部导航 */}
        <div className="border-t border-amber-brown/30 bg-ancient-card/90 backdrop-blur-sm">
          <div className="flex justify-around">
            <Button
              variant="ghost"
              className="flex-1 flex flex-col items-center py-2 md:py-3 rounded-none text-amber-brown bg-amber-brown/10"
              onClick={() => router.push("/")}
            >
              <div className="flex flex-col items-center gap-0.5">
                <BookOpen className="h-4 w-4 md:h-5 md:w-5" />
                <span className="text-xs">精进</span>
              </div>
            </Button>
            <Button
              variant="ghost"
              className="flex-1 flex flex-col items-center py-2 md:py-3 rounded-none text-ancient-text/70 hover:bg-amber-brown/5"
              onClick={() => router.push("/sells")}
            >
              <div className="flex flex-col items-center gap-0.5">
                <Heart className="h-4 w-4 md:h-5 md:w-5" />
                <span className="text-xs">随喜</span>
              </div>
            </Button>
            <Button
              variant="ghost"
              className="flex-1 flex flex-col items-center py-2 md:py-3 rounded-none text-ancient-text/70 hover:bg-amber-brown/5"
              onClick={() => router.push("/my")}
            >
              <div className="flex flex-col items-center gap-0.5">
                <User className="h-4 w-4 md:h-5 md:w-5" />
                <span className="text-xs">我执</span>
              </div>
            </Button>
          </div>
        </div>
      </div>
    )
  }

  // 根据状态决定渲染欢迎页面还是校对页面
  if (showWelcome) {
    return renderWelcomePage()
  }

  return (
    <div className={`w-[100vw] h-[100vh] overflow-auto bg-ancient-scroll font-ancient text-ancient-text`}>
      {isManualLinking && (
        <div className="fixed top-16 left-0 right-0 bg-blue-100 text-blue-800 p-2 text-center z-50">
          {manualLinkStep === 0 ? "请点击原文中的字符" : "请点击校对文本中的字符完成链接"}
          <button className="ml-2 text-blue-600 hover:text-blue-800" onClick={() => setIsManualLinking(false)}>
            取消
          </button>
        </div>
      )}
      {isRemoveMode && (
        <div className="fixed top-16 left-0 right-0 bg-purple-100 text-purple-800 p-2 text-center z-50">
          请选择需要标记为非正文的原文字符 (已选择: {selectedForRemoval.length + afterRemoval.length}个)
          <button
            className="ml-2 text-purple-600 hover:text-purple-800"
            onClick={() => {
              setIsRemoveMode(false)
              setSelectedForRemoval([])
              setAfterRemoval([])
            }}
          >
            取消
          </button>
        </div>
      )}
      {isMagnifyMode && (
        <div className="fixed top-16 left-0 right-0 bg-blue-100 text-blue-800 p-2 text-center z-50">
          请选择需要查看详情的字符
          <button
            className="ml-2 text-blue-600 hover:text-blue-800"
            onClick={() => {
              setIsMagnifyMode(false)
            }}
          >
            取消
          </button>
        </div>
      )}

      {/* 放大查看弹窗 */}
      {/*{showMagnifyPopup && selectedCharForMagnify && (*/}
      {/*  <div*/}
      {/*    className="fixed inset-0 bg-black/30 flex items-center justify-center z-50 p-4"*/}
      {/*    onClick={closeMagnifyPopup}*/}
      {/*  >*/}
      {/*    <div*/}
      {/*      className="bg-ancient-card p-3 md:p-6 rounded-lg shadow-ancient max-w-md w-full mx-auto"*/}
      {/*      onClick={(e) => e.stopPropagation()} // 防止点击弹窗内容时关闭*/}
      {/*    >*/}
      {/*      <div className="flex justify-between items-center mb-2 md:mb-4">*/}
      {/*        <h3 className="text-sm md:text-lg font-medium text-amber-brown">*/}
      {/*          字符详情 - {selectedCharForMagnify.type === "original" ? "原文" : "校对"}*/}
      {/*        </h3>*/}
      {/*        <button*/}
      {/*          onClick={closeMagnifyPopup}*/}
      {/*          className="text-ancient-text/60 hover:text-ancient-text/90 transition-colors"*/}
      {/*          aria-label="关闭"*/}
      {/*        >*/}
      {/*          <X className="h-4 w-4 md:h-5 md:w-5" />*/}
      {/*        </button>*/}
      {/*      </div>*/}

      {/*      <div className="flex flex-col items-center gap-3 md:gap-4">*/}
      {/*        <div*/}
      {/*          className={`${isMobile ? "w-24 h-24" : "w-32 h-32"} border border-amber-brown/30 bg-ancient-card/80 rounded-md overflow-hidden flex items-center justify-center`}*/}
      {/*        >*/}
      {/*          {selectedCharForMagnify.imageUrl ? (*/}
      {/*            <img*/}
      {/*              src={*/}
      {/*                getSafeImageUrl(selectedCharForMagnify.imageUrl, selectedCharForMagnify.type) ||*/}
      {/*                "/placeholder.svg" ||*/}
      {/*                "/placeholder.svg"*/}
      {/*              }*/}
      {/*              alt={selectedCharForMagnify.content}*/}
      {/*              className="max-w-full max-h-full object-contain"*/}
      {/*            />*/}
      {/*          ) : (*/}
      {/*            <span className="text-3xl md:text-4xl font-bold text-amber-brown">*/}
      {/*              {selectedCharForMagnify.content || "?"}*/}
      {/*            </span>*/}
      {/*          )}*/}
      {/*        </div>*/}

      {/*        <div className="text-center">*/}
      {/*          <p className="text-base md:text-lg font-bold mb-1">{selectedCharForMagnify.content || "无内容"}</p>*/}
      {/*          <p className="text-xs md:text-sm text-ancient-text/70">*/}
      {/*            位置: {selectedCharForMagnify.position}*/}
      {/*            (第 {Math.floor(selectedCharForMagnify.position / charsPerPage) + 1} 页)*/}
      {/*          </p>*/}
      {/*          <p className="text-xs md:text-sm text-ancient-text/70">索引: {selectedCharForMagnify.index}</p>*/}
      {/*        </div>*/}
      {/*      </div>*/}

      {/*      <div className="mt-3 md:mt-4 text-center text-xs md:text-sm text-ancient-text/60">点击任意位置关闭</div>*/}
      {/*    </div>*/}
      {/*  </div>*/}
      {/*)}*/}
      <UserInfo ref={userinfoRef} projectInfo={projectInfo} isMobile={isMobile} active="精进" />

      {/* 分屏校对区域 */}
      <div
        className={`flex ${isVerticalLayout ? "flex-col" : "flex-row"} h-[calc(100vh-${isVerticalLayout ? "440px" : "340px"})]`}
      >
        {/* 左侧原文 */}
        <div
          id="original-panel"
          className={`${isVerticalLayout ? "w-full h-1/2" : "w-1/2 h-full"} ${isVerticalLayout ? "border-b" : "border-r"} border-amber-brown/30 p-4 flex flex-col`}
        >
          <div className="flex justify-between items-center mb-4">
            <h2 className="text-lg font-bold text-amber-brown text-center">原文</h2>
            <div className="flex items-center gap-2">
              <div className="flex items-center gap-1 text-sm text-ancient-text/70">
                <span>
                  {currentOriginalPage}/{totalOriginalPages}
                </span>
              </div>
              <Button
                data-testid="original-switch-btn"
                variant="outline"
                size="icon"
                onClick={() => toggleReadingMode("original")}
                className="bg-ancient-scroll/10 border-amber-brown/30 text-amber-brown hover:bg-amber-brown/10"
                title={originalReadingMode === "ancient" ? "切换到现代文排列" : "切换到古文排列"}
              >
                {originalReadingMode === "ancient" ? (
                  <LayoutGrid className="h-5 w-5" />
                ) : (
                  <BookText className="h-5 w-5" />
                )}
              </Button>
            </div>
          </div>
          <div ref={originalContainerRef} className="flex-grow flex flex-col overflow-y-auto">
            <div className="min-h-full w-full flex items-center justify-center">{renderOriginalChars()}</div>
          </div>
        </div>

        {/* 右侧校对 */}
        <div id="typeset-panel" className={`${isVerticalLayout ? "w-full h-1/2" : "w-1/2 h-full"} p-4 flex flex-col`}>
          <div className="flex justify-between items-center mb-4">
            <h2 className="text-lg font-bold text-amber-brown text-center">校对</h2>
            <div className="flex items-center gap-2">
              <div className="flex items-center gap-1 text-sm text-ancient-text/70">
                <span>
                  {currentTypesetPage}/{totalTypesetPages}
                </span>
              </div>
              <Button
                data-testid="typeset-switch-btn"
                variant="outline"
                size="icon"
                onClick={() => toggleReadingMode("typeset")}
                className="bg-ancient-scroll/10 border-amber-brown/30 text-amber-brown hover:bg-amber-brown/10"
                title={typesetReadingMode === "ancient" ? "切换到现代文排列" : "切换到古文排列"}
              >
                {typesetReadingMode === "ancient" ? (
                  <LayoutGrid className="h-5 w-5" />
                ) : (
                  <BookText className="h-5 w-5" />
                )}
              </Button>
            </div>
          </div>
          <div ref={typesetContainerRef} className="flex-grow flex flex-col overflow-y-auto">
            <div className="min-h-full w-full flex items-center justify-center">{renderTypesetChars()}</div>
          </div>
        </div>
      </div>

      {/* 工具栏 */}
      {!showMagnifyPopup && (
        <div
            ref={toolRef}
          className="fixed bottom-0 left-0 right-0 border-b-0 bg-ancient-card/90 backdrop-blur-sm p-2 flex flex-col sm:flex-row justify-between items-center gap-2 z-20">
          <div className="flex justify-center gap-1 sm:gap-2 flex-wrap">
            <Button
              variant="outline"
              size={isMobile ? "sm" : "icon"}
              onClick={goToPrevPage}
              disabled={currentOriginalPage <= 1 && currentTypesetPage <= 1}
              className="bg-ancient-scroll/10 border-amber-brown/30 text-amber-brown hover:bg-amber-brown/10"
              title="上一页"
            >
              <ChevronLeft className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}/>
            </Button>
            <div className="flex items-center justify-center min-w-[3rem] text-sm text-ancient-text/80">
              {currentOriginalPage}/{totalOriginalPages}
            </div>
            <Button
              variant="outline"
              size={isMobile ? "sm" : "icon"}
              onClick={goToNextPage}
              disabled={currentOriginalPage >= totalOriginalPages && currentTypesetPage >= totalTypesetPages}
              className="bg-ancient-scroll/10 border-amber-brown/30 text-amber-brown hover:bg-amber-brown/10"
              title="下一页"
            >
              <ChevronRight className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}/>
            </Button>
            <Button
              variant="outline"
              size={isMobile ? "sm" : "icon"}
              onClick={confirmChar}
              className="bg-ancient-scroll/10 border-amber-brown/30 text-green-600 hover:bg-amber-brown/10"
              title="确认"
            >
              <CheckCircle className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}/>
            </Button>
            <Button
              variant="outline"
              size={isMobile ? "sm" : "icon"}
              onClick={markCharProblem}
              className="bg-ancient-scroll/10 border-amber-brown/30 text-red-600 hover:bg-amber-brown/10"
              title="标记问题"
            >
              <HelpCircle className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}/>
            </Button>
            <Button
              variant="outline"
              size={isMobile ? "sm" : "icon"}
              onClick={skipChar}
              className="bg-ancient-scroll/10 border-amber-brown/30 text-blue-600 hover:bg-amber-brown/10"
              title="跳过（排版多字）"
            >
              <SkipForward className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}/>
            </Button>
            <Button
              variant="outline"
              size={isMobile ? "sm" : "icon"}
              onClick={insertChar}
              className="bg-ancient-scroll/10 border-amber-brown/30 text-purple-600 hover:bg-amber-brown/10"
              title="插入（排版少字）"
            >
              <PlusCircle className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}/>
            </Button>
            <Button
              variant="outline"
              size={isMobile ? "sm" : "icon"}
              onClick={startManualLinking}
              className={`bg-ancient-scroll/10 border-amber-brown/30 ${isManualLinking ? "bg-blue-100 text-blue-600" : "text-amber-brown"} hover:bg-amber-brown/10`}
              title="手动链接字符"
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                width="24"
                height="24"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
                className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}
              >
                <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
                <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
              </svg>
            </Button>
            <Button
              variant="outline"
              size={isMobile ? "sm" : "icon"}
              onClick={() => {
                // Toggle remove mode
                setIsRemoveMode(!isRemoveMode)
                setIsMagnifyMode(false)

                // If we're exiting remove mode and have selections, process them
                if (isRemoveMode) {
                  // Mark all selected characters as removed
                  if (selectedForRemoval.length > 0) {
                    setConfirmedChars((prev) => {
                      const updated = {...prev}
                      selectedForRemoval.forEach((index) => {
                        const key = `remove-origin-${index}`
                        updated[key] = {
                          status: "removed",
                          originalIndex: index,
                        }
                      })
                      return updated
                    })

                    // Add to history
                    addToHistory({
                      type: "remove-origin",
                      list: selectedForRemoval,
                      description: `去除字符: ${selectedForRemoval.length}个字符被标记为非正文`,
                    })

                    // 如果当前索引在被标记为非正文的字符中，自动跳到下一个未被标记的字符
                    if (selectedForRemoval.includes(currentOriginalIndex)) {
                      // 找到下一个未被标记为非文本的字符索引
                      let nextValidIndex = currentOriginalIndex + 1
                      while (
                          nextValidIndex < originalChars.length &&
                          (selectedForRemoval.includes(nextValidIndex) || confirmedChars[`remove-${nextValidIndex}`])
                          ) {
                        nextValidIndex++
                      }
                      setCurrentOriginalIndex(nextValidIndex)
                    }
                  } else if (afterRemoval.length > 0) {
                    setConfirmedChars((prev) => {
                      const updated = {...prev}
                      afterRemoval.forEach((index) => {
                        const key = `remove-after-${index}`
                        updated[key] = {
                          status: "removed",
                          originalIndex: index,
                        }
                      })
                      return updated
                    })

                    // Add to history
                    addToHistory({
                      type: "remove-after",
                      list: afterRemoval,
                      description: `去除字符: ${afterRemoval.length}个字符被标记为非正文`,
                    })
                    if (afterRemoval.includes(currentTypesetIndex)) {
                      // 找到下一个未被标记为非文本的字符索引
                      let nextValidIndex = currentTypesetIndex + 1
                      while (
                          nextValidIndex < originalChars.length &&
                          (selectedForRemoval.includes(nextValidIndex) || confirmedChars[`remove-${nextValidIndex}`])
                          ) {
                        nextValidIndex++
                      }
                      setCurrentTypesetIndex(nextValidIndex)
                    }
                  }

                  // Update completion count
                  setCompletedChars((prev) => Math.min(prev + selectedForRemoval.length, totalChars))

                  // Clear selections
                  setSelectedForRemoval([])
                  setAfterRemoval([])
                }
              }}
              className={`bg-ancient-scroll/10 border-amber-brown/30 ${isRemoveMode ? "bg-purple-100 text-purple-600 ring-2 ring-purple-500" : "text-red-500"} hover:bg-amber-brown/10`}
              title="去除（标记为非正文）"
            >
              <Trash2 className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}/>
            </Button>
            <Button
              variant="outline"
              size={isMobile ? "sm" : "icon"}
              onClick={() => {
                // Toggle magnify mode
                setIsMagnifyMode(!isMagnifyMode)
                setIsRemoveMode(false)

                // If we're exiting magnify mode, reset state
                if (isMagnifyMode) {
                  setSelectedCharForMagnify(null)
                  setShowMagnifyPopup(false)
                }
              }}
              className={`bg-ancient-scroll/10 border-amber-brown/30 ${isMagnifyMode ? "bg-blue-100 text-blue-600 ring-2 ring-blue-500" : "text-amber-brown"} hover:bg-amber-brown/10`}
              title="放大查看字符"
            >
              <Search className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}/>
            </Button>
            <Button
              ref={undoButtonRef}
              variant="outline"
              size={isMobile ? "sm" : "icon"}
              onClick={undoLastOperation}
              onMouseDown={handleUndoButtonMouseDown}
              onMouseUp={handleUndoButtonMouseUp}
              onMouseLeave={handleUndoButtonMouseUp}
              onContextMenu={handleUndoButtonContextMenu}
              className="bg-ancient-scroll/10 border-amber-brown/30 text-amber-brown hover:bg-amber-brown/10"
              title="撤销上一步操作 (长按或右键查看历史)"
              disabled={operationHistory.length === 0}
            >
              <Undo2 className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}/>
            </Button>
          </div>

          <div className="flex items-center gap-3 w-full md:w-auto">
            <div className="text-sm text-ancient-text/80 whitespace-nowrap">
              {completedChars}/{totalChars}
            </div>
            <div className="w-full md:w-48 flex-1">
              <Progress value={progressPercentage} className="h-2 bg-ancient-scroll/50"/>
            </div>
            <div className="text-sm text-ancient-text/80 whitespace-nowrap">{progressPercentage}%</div>
            <Button
              variant="outline"
              size={isMobile ? "sm" : "icon"}
              onClick={toggleFinalDraft}
              className="bg-ancient-scroll/10 border-amber-brown/30 text-amber-brown hover:bg-amber-brown/10"
              title={showFinalDraft ? "显示校对视图" : "显示终稿视图"}
            >
              {showFinalDraft ? (
                <Eye className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}/>
              ) : (
                <FileText className={`${isMobile ? "h-4 w-4" : "h-5 w-5"}`}/>
              )}
            </Button>
          </div>
        </div>
      )}
      {/* 历史记录悬浮窗 */}
      {showHistory && (
        <div className="fixed inset-0 bg-black/30 flex items-center justify-center z-50 p-2 md:p-4">
          <div className="bg-ancient-card rounded-lg shadow-ancient max-w-md w-full max-h-[80vh] overflow-hidden">
            <div className="flex justify-between items-center p-3 md:p-4 border-b border-amber-brown/30">
              <div className="flex items-center gap-2">
                <Clock className="h-4 w-4 md:h-5 md:w-5 text-amber-brown"/>
                <h3 className="text-base md:text-lg font-bold text-amber-brown">操作历史</h3>
              </div>
              <Button
                variant="ghost"
                size="sm"
                onClick={closeHistoryWindow}
                className="text-ancient-text/60 hover:text-ancient-text/90 hover:bg-amber-brown/10"
              >
                <X className="h-4 w-4 md:h-5 md:w-5"/>
              </Button>
            </div>
            <div className="p-3 md:p-4 overflow-y-auto max-h-[60vh]">
              {operationHistory.length > 0 ? (
                <ul className="space-y-2">
                  {operationHistory.map((op) => (
                    <li key={op.id} className="p-2 border-b border-amber-brown/20 last:border-0">
                      <div className="flex justify-between items-start">
                        <div>
                          <span className="text-sm md:text-base font-medium">{op.description}</span>
                          <div className="text-xs text-ancient-text/60 mt-1">
                            {op.type === "confirm" && <CheckCircle className="inline h-3 w-3 text-green-600 mr-1"/>}
                            {op.type === "problem" && <HelpCircle className="inline h-3 w-3 text-red-600 mr-1"/>}
                            {op.type === "skip" && <SkipForward className="inline h-3 w-3 text-blue-600 mr-1"/>}
                            {op.type === "insert" && <PlusCircle className="inline h-3 w-3 text-purple-600 mr-1"/>}
                            {op.type === "undo" && <Undo2 className="inline h-3 w-3 text-amber-brown mr-1"/>}
                            {op.type === "manual-link" && (
                              <svg
                                xmlns="http://www.w3.org/2000/svg"
                                width="16"
                                height="16"
                                viewBox="0 0 24 24"
                                fill="none"
                                stroke="currentColor"
                                strokeWidth="2"
                                strokeLinecap="round"
                                strokeLinejoin="round"
                                className="inline h-3 w-3 text-blue-600 mr-1"
                              >
                                <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
                                <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
                              </svg>
                            )}
                            {op.type === "remove" && (
                              <svg
                                xmlns="http://www.w3.org/2000/svg"
                                width="16"
                                height="16"
                                viewBox="0 0 24 24"
                                fill="none"
                                stroke="currentColor"
                                strokeWidth="2"
                                strokeLinecap="round"
                                strokeLinejoin="round"
                                className="inline h-3 w-3 text-red-500 mr-1"
                              >
                                <path
                                  d="M3 6h18M5 6l1 14c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2L19 6M14 6V4c0-1.1-.9-2-2-2h-4c-1.1 0-2 .9-2 2v2"></path>
                              </svg>
                            )}
                            {op.originalIndex !== undefined && `原文索引: ${op.originalIndex}`}
                            {op.typesetIndex !== undefined && op.originalIndex !== undefined && " | "}
                            {op.typesetIndex !== undefined && `校对索引: ${op.typesetIndex}`}
                          </div>
                        </div>
                        <span className="text-xs text-ancient-text/60">{op.timestamp}</span>
                      </div>
                    </li>
                  ))}
                </ul>
              ) : (
                <div className="text-center py-6 md:py-8 text-ancient-text/60">暂无操作历史</div>
              )}
            </div>
          </div>
        </div>
      )}

      {/* 添加确认对话框 */}
      {showConfirmDialog && (
        <div className="fixed inset-0 bg-black/30 flex items-center justify-center z-50 p-3 md:p-4">
          <div className="bg-ancient-card p-3 md:p-6 rounded-lg shadow-ancient max-w-md w-full mx-auto">
            <div className="flex justify-between items-center mb-2 md:mb-4">
              <h3 className="text-base md:text-lg font-medium text-amber-brown">确认操作</h3>
              <button
                onClick={closeConfirmDialog}
                className="text-ancient-text/60 hover:text-ancient-text/90 transition-colors"
                aria-label="关闭"
              >
                <X className="h-4 w-4 md:h-5 md:w-5"/>
              </button>
            </div>
            <p className="mb-4 md:mb-6 text-sm md:text-base">{confirmMessage}</p>
            <div className="flex justify-end gap-3">
              <Button
                variant="outline"
                size={isMobile ? "sm" : "default"}
                className="border-amber-brown/30 text-amber-brown hover:bg-amber-brown/10 text-sm h-8 md:h-9"
                onClick={closeConfirmDialog}
              >
                取消
              </Button>
              <Button
                size={isMobile ? "sm" : "default"}
                className="bg-amber-brown hover:bg-amber-brown-dark text-ancient-scroll text-sm h-8 md:h-9"
                onClick={executeConfirmAction}
              >
                确认
              </Button>
            </div>
          </div>
        </div>
      )}
      <VisibleControl visible={showMagnifyPopup}>
        <CharDetailModal char={selectedCharForMagnify} onCancel={() => setShowMagnifyPopup(false)} />
      </VisibleControl>
      <Toaster />
    </div>
  )
}
